package classpath

import (
	"os"
	"path/filepath"
)

/*
todo 实现类加载机制，即加载请求顺序为： 用户类路径 -> 扩展类类路径 -> 启动类路径, 加载路径为 启动类路径 -> 扩展类类路径 -> 用户类路径
所有的类加载时必须先从启动类开始加载！！ 保证了Object在所有类中都是一样的(同一个Object类)
*/
type Classpath struct {
	bootClasspath Entry // 启动类路径
	extClasspath  Entry // 扩展类路径
	userClasspath Entry // 用户类路径
}

func Parse(jreOption, cpOption string) *Classpath {
	cp := &Classpath{}
	cp.parseBootAndExtClasspath(jreOption)
	cp.parseUserClasspath(cpOption)
	return cp
}

// 如若用户没有提供 -classpath/-cp选项，则使用当前目录作为用户类路径
func (self *Classpath) ReadClass(className string) ([]byte, Entry, error) {
	className = className + ".class"
	if data, entry, err := self.bootClasspath.readClass(className); err == nil {
		return data, entry, err
	}
	if data, entry, err := self.extClasspath.readClass(className); err == nil {
		return data, entry, err
	}
	return self.userClasspath.readClass(className)
}

func (self *Classpath) String() string {
	return self.userClasspath.String()
}

// 解析启动类路径和扩展类路径
func (self *Classpath) parseBootAndExtClasspath(jreOption string) {
	jreDir := getJreDir(jreOption)

	// 启动类：位于JRE的lib目录，即 jre/lib/*
	jreLibPath := filepath.Join(jreDir, "lib", "*")
	self.bootClasspath = newWildcardEntry(jreLibPath)

	// 扩展类：位于JRE的lib目录下的ext中, 即 jre/lib/ext/*
	jreExtPath := filepath.Join(jreDir, "lib", "ext", "*")
	self.extClasspath = newWildcardEntry(jreExtPath)
}

func getJreDir(jreOption string) string {
	// 优先使用用户输入的 -Xjre 作为jre目录
	if jreOption != "" && Exists(jreOption) {
		return jreOption
	}
	// 没有输入选项，则在当前目录下寻找jre目录
	if Exists(".jre") {
		return ".jre"
	}
	// 以上两者都找不到，尝试获取并使用JAVA_HOME里面的变量
	if jh := os.Getenv("JAVA_HOME"); jh != "" {
		return filepath.Join(jh, "jre")
	}
	// 都未找到，报错
	panic("Can not find jre folder")
}

// 工具函数，判断是否存在
func Exists(path string) bool {
	if _, err := os.Stat(path); err != nil {
		if os.IsNotExist(err) {
			return false
		}
	}
	return true
}

func (self *Classpath) parseUserClasspath(cpOption string) {
	if cpOption == "" {
		cpOption = "."
	}
	self.userClasspath = newEntry(cpOption)
}
